#define _CRT_SECURE_NO_WARNINGS

#include "contact.h"

// Check capacity, extends it for shortage
void checkCapacity(Contact* pc) {
	if (pc->count == pc->capacity) {
		MemberInfo* ptr = (MemberInfo*)realloc(pc->data,
			(pc->capacity + DEFAULT_CAPACITY_ADD) * sizeof(MemberInfo));
		if (ptr == NULL) {
			perror("AddMember");
			return ;
		}
		pc->data = ptr;
		pc->capacity += DEFAULT_CAPACITY_ADD;
		printf("CHECK> Capacity extend success\n");
	}
}

// Load contact list from file
void loadContact(Contact* pc) {
	assert(pc);
	// Open file
	FILE* pfRead = fopen("contactList.txt", "rb");
	if (pfRead == NULL) {
		perror("LoadContact");
		return ;
	}
	// File operation
	MemberInfo tmp = { 0 };
	while (fread(&tmp, sizeof(MemberInfo), 1, pfRead) == 1) {
		// Check capacity, extends it for shortage
		checkCapacity(pc);
		// Load members
		pc->data[pc->count] = tmp;
		pc->count++;
	}
	// Close file
	fclose(pfRead);
	pfRead = NULL;
}

// Contact list initialization
int initContact(Contact* pc) {
	assert(pc);
	pc->count = 0;
	pc->data = (MemberInfo*)calloc(DEFAULT_CAPACITY, sizeof(MemberInfo));
	if (pc->data == NULL) {
		perror("InitContact");
		return 1;
	}
	pc->capacity = DEFAULT_CAPACITY;
	// Load date
	loadContact(pc);
	return 0;
}

// Save contact list
void saveContact(const Contact* pc) {
	assert(pc);
	// Open file
	FILE* pfWrite = fopen("contactList.txt", "wb");
	if (pfWrite == NULL) {
		perror("SaveContact");
		return ;
	}
	// Save data
	for (int i = 0; i < pc->count; i++) {
		fwrite(pc->data + i, sizeof(MemberInfo), 1, pfWrite);
	}
	// Close file
	fclose(pfWrite);
	pfWrite = NULL;
}

// Destroy contact list
void destroyContact(Contact* pc) {
	assert(pc);
	free(pc->data);
	pc->data = NULL;
}

// Wait for a key from keyboard
void waitMoment() {
	char input = 0;
	do {
		getchar();
		printf("> Enter 'c' to continue ...\n");
		scanf("%c", &input);
	} while (input != 'c');
}

// Display a member
void displayMember(Contact* pc, int index) {
	printf("%-19s  %3s  %-6s  %-11s  %-28s\n",
		"NAME", "AGE", "GENDER", "TELEPHONE", "ADDRESS");
	printf("%-19s  %3d  %-6s  %-11s  %-28s\n",
		pc->data[index].name,
		pc->data[index].age,
		pc->data[index].gender,
		pc->data[index].tele,
		pc->data[index].addr);
}

// Add a member
void addMember(Contact* pc) {
	assert(pc);

	// Check capacity, extends it for shortage
	checkCapacity(pc);

	printf("ADD> Please enter name:v\n");
	scanf("%s", pc->data[pc->count].name);
	printf("ADD> Please enter age:v\n");
	scanf("%d", &(pc->data[pc->count].age)); 
	printf("ADD> Please enter gender:v\n");
	scanf("%s", pc->data[pc->count].gender);
	printf("ADD> Please enter telephone number:v\n");
	scanf("%s", pc->data[pc->count].tele);
	printf("ADD> Please enter address:v\n");
	scanf("%s", pc->data[pc->count].addr);

	system("cls");
	printf("ADD> Add member success\n");

	// Display
	printf("ADD> Member you have added:v\n");
	displayMember(pc, pc->count);

	pc->count++;
	waitMoment();
	system("cls");
}

// Display contact list
void displayContact(Contact* pc) {
	printf("%-19s  %3s  %-6s  %-11s  %-28s\n",
		"NAME", "AGE", "GENDER", "TELEPHONE", "ADDRESS");
	for (int i = 0; i < pc->count; i++) {
		printf("%-19s  %3d  %-6s  %-11s  %-28s\n",
			pc->data[i].name, 
			pc->data[i].age, 
			pc->data[i].gender, 
			pc->data[i].tele, 
			pc->data[i].addr);
	}

	waitMoment();
	system("cls");
}

// Find a member by name
int findByName(Contact* pc, char* name) {
	assert(pc && name);
	for (int i = 0; i < pc->count; i++) {
		if (strcmp(pc->data[i].name, name) == 0) {
			return i;
		}
	}
	return -1;
}

// Delete a member
void deleteMember(Contact* pc) {
	assert(pc);
	char name[MAX_NAME] = { 0 };
	if (pc->count == 0) {
		printf("No member");
		waitMoment();
		system("cls");
		return ;
	}
	printf("DELETE> Plaese enter a name to delete:v\n");
	scanf("%s", name);
	int pos = findByName(pc, name);
	if (pos == -1) {
		printf("Member not found\n");
		waitMoment();
		system("cls");
		return ;
	}
	system("cls");

	// Display member and confirm choice
	printf("DELETE> Member have found:v\n");
	displayMember(pc, pos);
	char input = 0;
	do {
		printf("DELETE> Do you want to delete this member? (y/n):");
		getchar();
		scanf("%c", &input);
		if (input == 'y') {
			break;		
		}
		if (input == 'n') {
			printf("DELETE> Delete cancel\n");
			waitMoment();
			system("cls");
			return ;
		}
		printf("DELETE> Input error\n");
	} while (input != 'y' && input != 'n');

	for (int i = pos; i < pc->count - 1; i++) {
		pc->data[i] = pc->data[i + 1];
	}
	pc->count--;
	printf("DELETE> Delete success\n");
	waitMoment();
	system("cls");
}

// Search a member
void searchMember(Contact* pc) {
	assert(pc);
	char name[MAX_NAME] = { 0 };
	if (pc->count == 0) {
		printf("SEARCH> No member");
		waitMoment();
		system("cls");
		return ;
	}
	printf("SEARCH> Please enter a name to search:v\n");
	scanf("%s", name);
	int pos = findByName(pc, name);
	if (pos == -1) {
		printf("SEARCH> Member not found\n");
		waitMoment();
		system("cls");
		return ;
	}
	printf("SEARCH> Search success\n");
	displayMember(pc, pos);
	waitMoment();
	system("cls");
}

// Modify a member
void modifyMember(Contact* pc) {
	assert(pc);
	char name[MAX_NAME] = { 0 };
	if (pc->count == 0) {
		printf("MODIFY> No member");
		waitMoment();
		system("cls");
		return ;
	}
	printf("MODIFY> Plaese enter a name to modify:v\n");
	scanf("%s", name);
	int pos = findByName(pc, name);
	if (pos == -1) {
		printf("MODIFY> Member not found\n");
		waitMoment();
		system("cls");
		return ;
	}

	// Display member
	displayMember(pc, pos);

	printf("MODIFY> Please enter name:v\n");
	scanf("%s", pc->data[pos].name);
	printf("MODIFY> Please enter age:v\n");
	scanf("%d", &(pc->data[pos].age));
	printf("MODIFY> Please enter gender:v\n");
	scanf("%s", pc->data[pos].gender);
	printf("MODIFY> Please enter telephone number:v\n");
	scanf("%s", pc->data[pos].tele);
	printf("MODIFY> Please enter address:v\n");
	scanf("%s", pc->data[pos].addr);

	printf("MODIFY> Modify success\n");
	waitMoment();
	system("cls");
}

// Compare two members by name
int cmpByName(const void* e1, const void* e2) {
	return strcmp(((MemberInfo*)e1)->name, ((MemberInfo*)e2)->name);
}

// Sort Contact list
void sortContact(Contact* pc) {
	assert(pc);
	qsort(pc->data, pc->count, sizeof(MemberInfo), cmpByName);
	printf("SORT> Sort complete\n");
	waitMoment();
	system("cls");
}